package org.eva.libra.spring.boot.security.oauth.config;

import java.util.concurrent.TimeUnit;

import javax.sql.DataSource;

import org.eva.libra.spring.boot.security.oauth.service.CustomAuthenticationEntryPoint;
import org.eva.libra.spring.boot.security.oauth.service.CustomLogoutSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

@Configuration
public class OAuth2Configuration {

	@Configuration
	@EnableResourceServer
	protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{

		@Autowired
		private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

		@Autowired
		private CustomLogoutSuccessHandler customLogoutSuccessHandler;

		@Override
		public void configure(HttpSecurity http) throws Exception{
			http.exceptionHandling()
			.authenticationEntryPoint(customAuthenticationEntryPoint)
			.and()
			.logout()
			.logoutUrl("/oauth/logout")
			.logoutSuccessHandler(customLogoutSuccessHandler)
			.and()
			.authorizeRequests()
			.antMatchers("/hello").permitAll()
			.antMatchers("/secure/**").authenticated();
		}
	}

	@Configuration
	@EnableAuthorizationServer
	public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware {

		private static final String ENV_OAUTH="authentication.oauth";
		private static final String PROP_CLIENTID="clientid";
		private static final String PROP_SECRET="secret";
		private static final String PROP_TOKEN_VALIDITY_SECONDS="tokenValidityInSeconds";

		private RelaxedPropertyResolver propertyResolver;

		@Autowired
		private DataSource dataSource;

		@Bean
		public TokenStore tokenStore(){
			return new JdbcTokenStore(dataSource);
		}

		@Autowired
		@Qualifier("authenticationManagerBean")
		private AuthenticationManager authenticationManager;

		@Bean // 声明 ClientDetails实现
	    public ClientDetailsService clientDetails() {
	        return new JdbcClientDetailsService(dataSource);
	    }

		@Override
		public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception{
			endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);

			// 配置TokenServices参数
	        DefaultTokenServices tokenServices = new DefaultTokenServices();
	        tokenServices.setTokenStore(endpoints.getTokenStore());
	        tokenServices.setSupportRefreshToken(false);
	        tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
	        tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
	        tokenServices.setAccessTokenValiditySeconds( (int) TimeUnit.DAYS.toSeconds(30)); // 30天
	        endpoints.tokenServices(tokenServices);
		}

		@Override
		public void setEnvironment(Environment arg0) {
			// TODO Auto-generated method stub

		}

	}

}
